Skip to content

feat: add Lyrics role (LRC and CDG)#80

Open
OnFreund wants to merge 2 commits into
Sendspin:mainfrom
OnFreund:feat/lyrics-role
Open

feat: add Lyrics role (LRC and CDG)#80
OnFreund wants to merge 2 commits into
Sendspin:mainfrom
OnFreund:feat/lyrics-role

Conversation

@OnFreund
Copy link
Copy Markdown

Implements #79.

Summary

  • Adds a new lyrics@v1 role for clients that display track lyrics or karaoke subtitles
  • Supports two channels (0–1) and two formats: lrc (text with embedded timestamps) and cdg (CD+G binary karaoke)
  • Lyrics are delivered as binary messages (types 12–13, assigned from the previously reserved 000011xx slot), without transport timestamps since timing is embedded in the files themselves
  • Clients can toggle channels on/off via stream/request-format without reconnecting

Details

  • client/hello: new lyrics@v1_support object with channels[] declaring format per channel (lrc | cdg | none)
  • stream/start: new lyrics object confirming active channel formats
  • stream/request-format: new lyrics object for mid-session format/channel changes
  • stream/end: lyrics added to the roles array
  • Binary message IDs 12–13 assigned to Lyrics role
  • Clearing lyrics: empty binary message (type byte only, no payload)

🤖 Generated with Claude Code

@OnFreund
Copy link
Copy Markdown
Author

Note - even though we wanted to send the lyrics inline, I looked into CDG files and they can be quite large, so I went with binary messages after all. This also keeps it consistent with artwork.

Comment thread README.md

**Supported formats:**
- `lrc` - LRC text format with embedded timestamps (UTF-8 encoded)
- `cdg` - CD+G karaoke format (binary)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lrc files are pretty ubiquitous, but I haven't heard of CD+G before.
Why should we support CD+G? I mean if it's really niche we can't depend on Sendspin implementations supporting that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have the data to back this up unfortunately, but karaoke subtitles are not niche and are well supported by both hardware and software.

Copy link
Copy Markdown

@Hedda Hedda Apr 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lrc files are pretty ubiquitous, but I haven't heard of CD+G before.
Why should we support CD+G? I mean if it's really niche we can't depend on Sendspin implementations supporting that.

@maximmaxim345 CDG+G is not niche at all, it is an official standard for Audio-CD with Graphics (as Audio Compact Discs with digital images) that all professional Karaoke machines uses (such as used in Karaoke bars and home use), so almost all songs are available in that format.The ”G” stands for Graphics and as I understand the format is it just images for each character and as such does not need a font engine to display wierd characters for all languages. Anyway, more common nowadays are MP3+G which is just when an the redbook Audio-CD part been converted to MPG and the Graphics broken out to separate files (.cdg).

image

For player code reference I suggest check out the Kodi (formerly XBMC) codebase which supports CD+G and MP3+G

Quote from that Wikipedia article:

Along with dedicated karaoke machines, other consumer devices that play CD+G format CDs include the NEC TurboGrafx-CD (a CD-ROM peripheral for the TurboGrafx-16) and Turbo Duo, as well as the Japan-only successor the PC-FX, the Philips CD-i, the Sega CD, Sega Saturn,[5] the JVC X'Eye, the 3DO Interactive Multiplayer, the Amiga CD32 and Commodore CDTV, and the Atari Jaguar CD (an attachment for the Atari Jaguar). Some CD-ROM drives can also read this data. Pioneer's LaserActive player can also play CD+G discs, as long as either the PAC-S1/S-10 or PAC-N1/N10 game modules are installed.

Since 2003, some standalone DVD players have supported the CD+G format. Regular audio CD players will output only the audio tracks as if it was a normal music CD, unless otherwise designed to read the extra data (lyrics and images).[6]

CD+G karaoke albums are still made today by several UK and US manufacturers including Sunfly, Zoom Entertainments, SBI Karaoke and Vocal Star. Although the popularity of CD sales are dwindling the format is still widely used as MP3+G downloads.

Comment thread README.md
- `lrc` - LRC text format with embedded timestamps (UTF-8 encoded)
- `cdg` - CD+G karaoke format (binary)

**No transport timestamps:** Unlike audio or artwork, lyrics binary messages do not carry a server clock timestamp. Timing information is embedded within the lyrics data itself (e.g., `[mm:ss.xx]` tags in LRC, frame timing in CDG). The server sends lyrics at the start of each track; clients begin processing as soon as they receive them.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will the lyrics be in sync then if it's not aligned to any timestamp?
I mean:

  • What if you pause/stop playback in the mean time, the lyrics should also stop in that case
  • Depending on the networks latency, the position in the lyrics can be different every time.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec instructs clients how to calculate track progress - can't we use that progress value to show the right lyrics? This is what I'm currently doing in my client (which is downloading lyrics independently) and it's working well.

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md
OnFreund and others added 2 commits April 27, 2026 19:05
Closes Sendspin#79 on Sendspin/spec

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Drop channels: single stream per role (like audio), client declares
  supported_formats in priority order, server picks one
- Use stream/end instead of empty binary message to signal no lyrics
- Add max_size_bytes to lyrics@v1_support for low-memory clients

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants